package com.system.boss.optlog.service;

import java.io.InputStream;
import java.util.Enumeration;

import javax.annotation.Resource;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import com.alibaba.fastjson.JSONObject;
import com.system.boss.optlog.model.BossOptLog;
import com.system.core.security.jwt.JwtService;
import com.system.core.security.jwt.dto.UserJWT;
import com.system.core.utils.IpUtil;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

// preHandle：调用Controller某个方法之前
// postHandle：Controller之后调用，视图渲染之前，如果控制器Controller出现了异常，则不会执行此方法
// afterCompletion：不管有没有异常，这个afterCompletion都会被调用，在整个请求结束之后被调用，
// 也就是在DispatcherServlet 渲染了对应的视图之后执行（主要是用于进行资源清理工作）
@Service
@Slf4j
public class BossOptLogInterceptorService implements HandlerInterceptor {

	@Autowired
	private ApplicationEventPublisher applicationEventPublisher;
	@Value("${system.optlog.enable:false}")
	private boolean optlogEnable = false;
	@Resource
	private CustomOptLog customOptLog;
	@Resource
	private JwtService jwtService;
	
	private Long getUserid(JSONObject jsonObject) {
		if(jsonObject == null) {
			return 0L;
		}
		else {
			return jsonObject.getLong("userId");
		}
	}

	@Transactional
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		if(handler instanceof HandlerMethod) {
			HandlerMethod handlerMethod = (HandlerMethod) handler;

			Object loginUserInfo = SecurityUtils.getSubject().getPrincipal();
			BossOptLog bossOptLog = new BossOptLog();
			String tokenstr = request.getHeader("token");
			String version = request.getHeader("version");
			if(loginUserInfo!=null) {
				JSONObject jsonObject = (JSONObject) JSONObject.toJSON(loginUserInfo);
				String userName = (jsonObject == null ? "未登录用户" : jsonObject.getString("userName"));
				String nickName = (jsonObject == null ? "未登录用户" : jsonObject.getString("nickName"));
				Long userId = getUserid(jsonObject);
				
				bossOptLog.setSource(1);
				bossOptLog.setOptUserName(StringUtils.isBlank(nickName) ? userName : nickName);
				bossOptLog.setUserId(userId);
			} else if(tokenstr !=null && tokenstr!=""){
				try {
					UserJWT user = jwtService.verifyToken(tokenstr, UserJWT.class);
					bossOptLog.setSource(2);
					bossOptLog.setOptUserName(user.getNick()==null?user.getUserName():user.getNick());
					bossOptLog.setUserId(Long.parseLong(user.getUserId()));
				} catch (Exception e) {
					
				}
			} else {
				bossOptLog.setSource(-1);
				bossOptLog.setOptUserName("未知用户");
			}
			bossOptLog.setOptItemCode(handlerMethod.getShortLogMessage());
			bossOptLog.setIpAddr(IpUtil.getUserIpAddr(request));
			bossOptLog.setComment(version);
			
			setRequestParam(request, bossOptLog);
			
			try {
				customOptLog.record(bossOptLog);
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (optlogEnable) {
				applicationEventPublisher.publishEvent(bossOptLog);
			}
		}
	}

	private void setRequestParam(HttpServletRequest httpServletRequest, BossOptLog bossOptLog) {
		StringBuilder params = new StringBuilder("{");
		Enumeration<String> paramenum = httpServletRequest.getParameterNames();
		if(paramenum != null) {
			while (paramenum.hasMoreElements()) {
				String param = (String) paramenum.nextElement();
				params.append("'"+param+"'");
				params.append(" : ");
				Object paramValue = httpServletRequest.getParameter(param);
				if(paramValue == null) {
					params.append("null");
				} else if(NumberUtils.isCreatable(String.valueOf(paramValue))){
					params.append(paramValue);
				} else {
					params.append("'"+paramValue+"'");
				}
				params.append(",");
			}
		}
		params.append("}");
		
		try (InputStream inputStream = httpServletRequest.getInputStream()) {
			String bodyparam = IOUtils.toString(inputStream,"utf-8");
			if(StringUtils.isNotBlank(bodyparam)) {
				params.delete(0, params.length());
				params.append(" ");
				params.append(bodyparam);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		if(params.toString() != null && params.toString().length()>300) {
			log.debug("日志太长了，不记了");
		} else {
			bossOptLog.setParams(params.toString());
		}
	}

}
